package org.ricks.condition1;

import org.ricks.ioc.event.IEvent;
import org.ricks.ioc.utils.Logger;
import org.ricks.ioc.utils.StringUtils;

import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList;

public class ConditionManager {

    private static class SingleCase {
        public static final ConditionManager INSTANCE = new ConditionManager();
    }

    private ConditionManager() {
    }

    public static ConditionManager me() {
        return ConditionManager.SingleCase.INSTANCE;
    }


    private final Map<Class<? extends IEvent>, List<Condition>> conditionMap = new ConcurrentHashMap<>();

    @SafeVarargs
    public final void registerConditionForEvents(Condition condition, Class<? extends IEvent>... eventTypes) {
        for (Class<? extends IEvent> eventType : eventTypes) {
            conditionMap.computeIfAbsent(eventType, k -> new CopyOnWriteArrayList<>())
                    .add(condition);
        }
    }

    public void unregisterCondition(Condition condition) {
        conditionMap.values().forEach(list -> list.remove(condition));
    }

    public void handleEvent(IEvent event) {
        Class<? extends IEvent> eventType = event.getClass();
        conditionMap.getOrDefault(eventType, Collections.emptyList())
                .forEach(cond -> safelyEmit(event, cond));
    }

    private void safelyEmit(IEvent event, Condition cond) {
        try {
            cond.emit(event);
        } catch (Exception e) {
            Logger.error(StringUtils.format("Error handling event {}", event.getClass().getSimpleName()), e);
        }
    }
}
